package de.gameduell.framework.threads 
{
	/**
	 * special thread that allow to block all queues:
	 * 1. an AllBlockingThread joins registered every queue und block them
	 * 2. if all queues are blocked the excution of the target thread starts
	 * 3. when target thread is finished, all queues will be released
	 * 
	 * @author Ferry Trunschke
	 */
	public class AllBlockingThread extends ThreadAdapter implements IThread {
		
		public var registeredQueueIds:Array;
		public var threadPoolManager:ThreadPoolManager;
		public var targetThread:IThread;
		public var blockingThreadCount:int = 0;
		
		public function AllBlockingThread(threadPoolManager:ThreadPoolManager, registeredQueueIds:Array, targetThread:IThread) {
			this.registeredQueueIds = registeredQueueIds;
			this.threadPoolManager = threadPoolManager;
			this.targetThread = targetThread;
			
			// add this thread into all queues, except the internal all blocking queue
			// - insert a block into all queues, to avoid other threads jump in a free slot
			for each(var queueId:String in registeredQueueIds) {
				if (queueId != ThreadPoolManager.INTERNAL_ALL_BLOCKING_QUEUE) {
					threadPoolManager.handleEvent(new StartThreadRequest(queueId, this));
				}
			}
		}
		
		// example: show popup
		public override function onStartExecution():void {
			
			// count all other queues (except the internal all blocking queue)
			blockingThreadCount++;

			// start target callback in global queue
			if (blockingThreadCount == registeredQueueIds.length - 1) {
				threadPoolManager.handleEvent(new StartThreadRequest(ThreadPoolManager.INTERNAL_ALL_BLOCKING_QUEUE, targetThread));
			}			
		}
		
		// returns isRunning() || isBlocking()
		public override function run():Boolean {
			
			// avoid to call run orf target thread before it was started
			var targetNotStartedYet:Boolean = blockingThreadCount < registeredQueueIds.length - 1;
			if (targetNotStartedYet) {
				return true;
			}
			
			var startedAndRunning:Boolean = targetThread.run() && blockingThreadCount == registeredQueueIds.length - 1;
			return startedAndRunning;
		}

		// example: hide popup
		public override function onFinishExecution():void {
		}		
		
		public override function get isBlockingThread():Boolean {
			return true;
		}
		
		public override function get description():String {
			return "AllBlockingThread." + targetThread.description + " targetRun=" + targetThread.run();
		}
				
	}

}